﻿using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Windows.Controls;
using System.Windows.Media;
using Dsl.Ped.AddIn.Java.Generated;
using Dsl.Ped.Common.Commands;
using Dsl.Ped.Framework.Common;
using Dsl.Ped.Framework.Projections;
using Dsl.Ped.Framework.Projections.CollectionProjections.ExpandableCollection;

namespace Dsl.Ped.AddIn.Java.Projections.MethodProjection
{
    /// <summary>
    /// Factory method of the projection
    /// </summary>
    public static class MethodProjectionFactory
    {
        public static IProjection GetProjection<T,E>(Method source, Expression<Func<T>> methodNameExpression, Expression<Func<E>> parametersExpression, Action addParameterAction)
        {
            return ObjectProjectionFactory.GetBlockProjection(
                ObjectProjectionFactory.GetBlockProjection(
                    ValueProjectionFactory.GetTextBoxProjection(source, methodNameExpression),
                    GetParametersProjection(source, parametersExpression),
                    bp => { bp.Foreground = new SolidColorBrush(Colors.Red); }),
                bp =>
                {
                    bp.Orientation = Orientation.Vertical;
                    bp.StartTag = "{";
                    bp.EndTag = "}";
                });
        }

        private static IProjection GetParametersProjection<E>(Method source, Expression<Func<E>> parametersExpression)
        {
            return CollectionProjectionFactory.GetExpandableCollectionProjection(
                source, 
                parametersExpression, 
                null,
                GetCustomConfiguration(source));
        }

        private static Action<ExpandableCollectionProjection> GetCustomConfiguration(Method source)
        {
            return exp => {
                exp.Commands = new List<IMenuCommand>() {
                    new MenuCommand<Parameter>(
                        "Add Parameter",
                        (param) =>
                            {
                                int position = 0;
                                if (param != null) position = source.parameters.IndexOf((Parameter)param) + 1;
                                source.parameters.Insert(
                                    position,
                                    new Parameter()
                                        {
                                            name = "parameter",
                                            type = "Void"
                                        });
                            })
                };
                exp.RemoveItem = parameter =>
                    { source.parameters.Remove((Parameter)parameter); };
            };
        }
    }
}
